/**
 * @file BitacoraDAO.java
 * @brief Implementa la clase BitacoraDAO
 * 
 * Implementa la clase BitacoraDAO usada para manejar la información de
 * las bitocaras del sistema en la base de datos.
 * 
 * @author Catalina Pelegrin Gonzalez
 * @version 01.02
*/

package GestorUsuarios;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import Servicios.Conexion;

/**
 * @class BitacoraDAO
 * 
 * @brief Se encarga de realizar las operaciones para manejar la información de
 * 		  las bitacoras del sistema en la base de datos.
 * 
 *        Permite realizar busquedas, a�adir a la base de datos, etc con los objetos Bitacora.
 * 
 */
public class BitacoraDAO {
	
	/**
	 * @brief Cadenas relacionadas con la operacion
	 */
	private static final String OPERACION_ALTA = "a";
	private static final String OPERACION_BAJA = "b";
	private static final String OPERACION_MODIFICACION = "m";
	
	/**
	 * @brief Agrega el objeto Bitacora la BD.
	 * @param b Bitacora a agregar, no se tiene en cuenta el idBitacora que se quiere asignar, se autoincrementa
	 * @throws ClassNotFoundException, IOException, SQLException, IDException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static void add(Bitacora b)throws SQLException, IOException, ClassNotFoundException, IDException, NoSuchAlgorithmException {
		String operacion;
		if(b.getOperacion()==OperacionBitacora.ALTA)
			operacion = OPERACION_ALTA;
		else if(b.getOperacion()==OperacionBitacora.BAJA)
				operacion = OPERACION_BAJA;
		else operacion = OPERACION_MODIFICACION;
		
		DateFormat formatoFecha = new SimpleDateFormat("yyyy-MM-dd");
		
		Conexion.conectar();
		Conexion.actualizar("INSERT Bitacora (fecha,operacion,pertenece,gestiona) VALUES (" +
				"\'"+ formatoFecha.format(b.getFecha())+				
				"\', \'"+ operacion +
				"\', \'"+ b.getIdUsuario() +
				"\', \'"+ b.getIdGestor() +"\');");
		
		// Buscamos por id
		Bitacora[] bitacora_bd = get(b.getFecha(),b.getOperacion(),b.getIdUsuario(),b.getIdGestor());
		Bitacora bit_bd = bitacora_bd[0];
		Conexion.desconectar();
		// Establecemos el id asignado en la base de datos
		if(bit_bd==null) {
			throw new IDException();
		}
		b.setIdBitacora(bit_bd.getIdBitacora());
	}
	/**
	 * @brief Obtiene las instancias Bitacora que coincidan con los parametros no nulos 
	 * pasados como argumento. Si hay algun parametro nulo, este no sera tenido en cuenta
	 * para la busqueda.
	 * @param fech fecha de la Bitacora
	 * @param operacion operacion acerca de bitacora: ALTA, BAJA o MODIFICACION
	 * @param idu Identificador del Usuario
	 * @param idg Identificador del Gestor
	 * @return Un vector de objetos Bitacora obtenidos
	 * @throws ClassNotFoundException, IOException, SQLException
	 * @throws NoSuchAlgorithmException 
	 */
	public static Bitacora[] get(Date fech, OperacionBitacora operacion,Integer idu, Integer idg) throws SQLException, IOException, ClassNotFoundException, NoSuchAlgorithmException {

		Bitacora [] bitacoras = null;
		DateFormat formatoFecha = new SimpleDateFormat("yyyy-MM-dd");
		
		Conexion.conectar();
		
		String parte_sel = "WHERE ";
		if(fech!=null)
			parte_sel += "fecha = \'"+ formatoFecha.format(fech) +"\' AND ";
		
		if(operacion!=null)
			if(operacion == OperacionBitacora.ALTA)
				parte_sel += "operacion = \'"+ OPERACION_ALTA +"\'  AND ";
			else if(operacion == OperacionBitacora.BAJA)
				parte_sel += "operacion = \'"+ OPERACION_BAJA +"\'  AND ";
			else parte_sel += "operacion = \'"+ OPERACION_MODIFICACION +"\'  AND ";
		
		if(idu!=null)
			parte_sel += "pertenece = \'"+ idu +"\' AND ";
		if(idg!=null)
			parte_sel += "gestiona = \'"+ idg +"\' AND ";
		
		// Sustituimos coma final, por punto y coma
		parte_sel = parte_sel.substring(0, parte_sel.length()-4)+";";
		
		ResultSet tabla = Conexion.consultar("SELECT * FROM Bitacora " + parte_sel);

		ArrayList<Bitacora> list_bitacoras = new ArrayList<Bitacora>();
		while(tabla.next()) {
			String string_operacion = tabla.getString("operacion");
			OperacionBitacora oper;
			if(string_operacion.equals(OPERACION_ALTA))
				oper = OperacionBitacora.ALTA;
			else if(string_operacion.equals(OPERACION_BAJA))
			oper = OperacionBitacora.BAJA;
			else oper = OperacionBitacora.MODIFICACION;
			
			list_bitacoras.add(new Bitacora(tabla.getInt("idBitacora"),tabla.getDate("fecha"),oper,tabla.getInt("pertenece"),tabla.getInt("gestiona")));
		}
		Conexion.desconectar();	
		
		if(list_bitacoras.size()>0) {
			bitacoras = new Bitacora[list_bitacoras.size()];
			list_bitacoras.toArray(bitacoras);
			return bitacoras;
		}
		else return null;	
	}
	/**
	 * @brief Obtiene las instancias Bitacora que coincidan con un numero de identificacion
	 * @param idB numero identificativo de la Bitacora
	 * @return Un objeto Bitacora obtenido
	 * @throws ClassNotFoundException, IOException, SQLException
	 * @throws NoSuchAlgorithmException 
	 */
	public static Bitacora get(Integer idB) throws SQLException, IOException, ClassNotFoundException, NoSuchAlgorithmException, IDException {
		Bitacora b=null;
		
		Conexion.conectar();
		String parte_sel = "WHERE ";
		if(idB!=null)
			parte_sel += "idBitacora= \'"+ idB ;
		ResultSet tabla = Conexion.consultar("SELECT * FROM Bitacora WHERE idBitacora = "+ idB +";");
		if(tabla.next()) { // Encontrado
			String string_o = tabla.getString("operacion");
			OperacionBitacora oper;
			if(string_o.equals(OPERACION_ALTA))
				oper = OperacionBitacora.ALTA;
			else if(string_o.equals(OPERACION_BAJA))
				oper = OperacionBitacora.BAJA;
			else oper = OperacionBitacora.MODIFICACION;
			
			b = new Bitacora(tabla.getInt("idBitacora"), tabla.getDate("fecha"),oper,tabla.getInt("pertenece"),tabla.getInt("gestiona"));
		} else {
			b = null;
		}
		Conexion.desconectar();
		return b;
	}
	

	/**
	 * @brief Obtiene las instancias Bitacora asociadas al idUsuario en la fecha indicada 
	 * como parametro. Si la fecha es nula devolvera todos los objetos bitacora asociados
	 * al id.
	 * @param idUsuario Identificador de usuario del que queremos obtener las instancias Bitacora
	 * @param fecha Fecha 
	 * @return Un vector con los objetos Bitacora obtenidos.
	 * @throws ClassNotFoundException, IOException, SQLException, IDException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static Bitacora [] getEntrada(Integer idUsuario,Date fecha)throws SQLException, IOException, ClassNotFoundException, IDException, NoSuchAlgorithmException {
		Bitacora [] bitacoras=get(fecha, null,idUsuario, null);
		return bitacoras;
		}
		
/*	public static Bitacora [] getEntrada(Integer idUsuario,Date fecha)throws SQLException, IOException, ClassNotFoundException, IDException, NoSuchAlgorithmException {
		Bitacora [] bitacoras=null;
		DateFormat formatoFecha = new SimpleDateFormat("yyyy-MM-dd");
		Conexion.conectar();			
		String parte_sel = "WHERE ";
		if(fecha!=null)
			parte_sel += "fecha = \'"+ formatoFecha.format(fecha)+"\' AND ";
		
		if( idUsuario != null)
			parte_sel += "pertenece = "+ idUsuario;
		
		ResultSet tabla = Conexion.consultar("SELECT * FROM Bitacora " + parte_sel +";");
		
		ArrayList<Bitacora> list_bitacoras = new ArrayList<Bitacora>();
		
		while(tabla.next()) {
			String string_operacion = tabla.getString("operacion");
			Bitacora.Operacion oper;
			if(string_operacion.equals(OPERACION_ALTA))
				oper = Bitacora.Operacion.ALTA;
			else if(string_operacion.equals(OPERACION_BAJA))
			oper = Bitacora.Operacion.BAJA;
			else oper = Bitacora.Operacion.MODIFICACION;
			
			list_bitacoras.add(new Bitacora(tabla.getInt("idBitacora"),tabla.getDate("fecha"),oper,tabla.getInt("pertenece"),tabla.getInt("gestiona")));
		}
		Conexion.desconectar();	
		
		if(list_bitacoras.size()>0) {
			bitacoras = new Bitacora[list_bitacoras.size()];
			list_bitacoras.toArray(bitacoras);
			return bitacoras;
		}
		else return null;	
	}
	*/
	/**
	 * @brief Obtiene las instancias Bitacora asociadas al idGestor en la fecha indicada 
	 * como parametro. Si la fecha es nula devolvera todos los objetos bitacora asociados
	 * al id.
	 * @param idGestor Identificador del Gestor del que queremos obtener las instancias Bitacora
	 * @param fecha Fecha
	 * @return Un vector con los objetos Bitacora obtenidos.
	 * @throws ClassNotFoundException, IOException, SQLException, IDException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static Bitacora [] getGestion(Integer idGestor,Date fecha)throws SQLException, IOException, ClassNotFoundException, IDException, NoSuchAlgorithmException {
		Bitacora [] bitacoras=get(fecha, null,null, idGestor);
		return bitacoras;
		}
		
/*	public static Bitacora [] getGestion(Integer idGestor,Date fecha) throws SQLException, IOException, ClassNotFoundException, IDException, NoSuchAlgorithmException {
		Bitacora [] bitacoras=null;
		DateFormat formatoFecha = new SimpleDateFormat("yyyy-MM-dd");
		Conexion.conectar();			
		String parte_sel = "WHERE ";
		if(fecha!=null)
			parte_sel += "fecha = \'"+ formatoFecha.format(fecha)+"\' AND ";
		
		if( idGestor != null)
			parte_sel += "gestiona = "+ idGestor;
		
		ResultSet tabla = Conexion.consultar("SELECT * FROM Bitacora " + parte_sel +";");
				
		ArrayList<Bitacora> list_bitacoras = new ArrayList<Bitacora>();
		
		while(tabla.next()) {
			String string_operacion = tabla.getString("operacion");
			Bitacora.Operacion oper;
			if(string_operacion.equals(OPERACION_ALTA))
				oper = Bitacora.Operacion.ALTA;
			else if(string_operacion.equals(OPERACION_BAJA))
			oper = Bitacora.Operacion.BAJA;
			else oper = Bitacora.Operacion.MODIFICACION;
			
			list_bitacoras.add(new Bitacora(tabla.getInt("idBitacora"),tabla.getDate("fecha"),oper,tabla.getInt("pertenece"),tabla.getInt("gestiona")));
		}
		Conexion.desconectar();	
		
		if(list_bitacoras.size()>0) {
			bitacoras = new Bitacora[list_bitacoras.size()];
			list_bitacoras.toArray(bitacoras);
			return bitacoras;
		}
		else return null;
	}
*/	
	/**
	 * @brief Obtiene la ultima instancia Bitacora asociada al idUsuario.
	 * @param idUsuario Identificador del Usuario de que queremos obtener la ultima instancia Bitacora
	 * @return El objeto Bitacora obtenido.
	 * @throws ClassNotFoundException, IOException, SQLException, IDException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static Bitacora getUltimaEntradaBitacora(Integer idUsuario) throws SQLException, IOException, ClassNotFoundException, IDException, NoSuchAlgorithmException {
		Bitacora bitacora=null;	
		DateFormat formatoFecha = new SimpleDateFormat("yyyy-MM-dd");
		Conexion.conectar();			
		String parte_sel = "WHERE ";		
		if( idUsuario != null)
			parte_sel += "pertenece = "+ idUsuario;
		String parte_sel2 = "WHERE ";		
		if( idUsuario != null)
			parte_sel += "b.pertenece = "+ idUsuario;
		String parte_sel3 = "WHERE ";		
		if( idUsuario != null)
			parte_sel3 += "b2.pertenece = "+ idUsuario;
		/*ResultSet tabla = Conexion.consultar("SELECT * FROM Bitacora " +parte_sel+ 
				" AND idBitacora = (SELECT MAX( b.idBitacora )FROM Bitacora b"+parte_sel2+
				") AND fecha = (SELECT MAX( b2.fecha )FROM Bitacora b2 WHERE "+parte_sel3+");");
	*/
		
		ResultSet tabla = Conexion.consultar("SELECT * FROM Bitacora WHERE pertenece =" +idUsuario+
				" AND idBitacora = (SELECT MAX( b.idBitacora )FROM Bitacora b WHERE b.pertenece="+idUsuario+
				") AND fecha = (SELECT MAX( b2.fecha )FROM Bitacora b2 WHERE b2.pertenece="+idUsuario+");");
		if(tabla.next()) {
			String string_operacion = tabla.getString("operacion");
			OperacionBitacora oper;
			if(string_operacion.equals(OPERACION_ALTA))
				oper = OperacionBitacora.ALTA;
			else if(string_operacion.equals(OPERACION_BAJA))
			oper = OperacionBitacora.BAJA;
			else oper = OperacionBitacora.MODIFICACION;			
			bitacora= new Bitacora(tabla.getInt("idBitacora"),tabla.getDate("fecha"),oper,tabla.getInt("pertenece"),tabla.getInt("gestiona"));
		}
		else bitacora=null;
		Conexion.desconectar();	
		return bitacora;	
	}

}
